package com.junmo.wechat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junmo.common.constant.GlobalConstants;
import com.junmo.common.constant.SecurityConstants;
import com.junmo.common.enums.RemindCode;
import com.junmo.common.exception.RemindException;
import com.junmo.common.redis.utils.RedisUtils;
import com.junmo.common.util.*;
import com.junmo.wechat.constant.WechatConstant;
import com.junmo.wechat.pojo.dto.*;
import com.junmo.wechat.mapper.UmsMemberMapper;
import com.junmo.wechat.pojo.entity.SysMember;
import com.junmo.wechat.pojo.vo.MemberVO;
import com.junmo.wechat.service.IMemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 会员业务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MemberServiceImpl extends ServiceImpl<UmsMemberMapper, SysMember> implements IMemberService {

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public IPage<SysMember> list(Page<SysMember> page, String nickname) {
        List<SysMember> list = this.baseMapper.list(page, nickname);
        page.setRecords(list);
        return page;
    }

    /**
     * 根据 openid 获取会员认证信息
     *
     * @param openid
     * @return
     */
    @Override
    public MemberAuthInfoDTO getByOpenid(String openid) {
        SysMember member = this.getOne(new LambdaQueryWrapper<SysMember>()
                .eq(SysMember::getOpenid, openid)
                .select(SysMember::getId,
                        SysMember::getOpenid,
                        SysMember::getStatus
                )
        );
        Assert.isTrue(member != null, "会员不存在");

        MemberAuthInfoDTO memberAuth = new MemberAuthInfoDTO()
                .setMemberId(member.getId())
                .setUsername(member.getOpenid())
                .setStatus(member.getStatus());
        return memberAuth;
    }

    /**
     * 根据手机号获取会员认证信息
     *
     * @param mobile
     * @return
     */
    @Override
    public MemberAuthInfoDTO getByMobile(String mobile) {
        SysMember member = this.getOne(new LambdaQueryWrapper<SysMember>()
                .eq(SysMember::getMobile, mobile)
                .select(SysMember::getId,
                        SysMember::getOpenid,
                        SysMember::getStatus
                )
        );
        Assert.isTrue(member != null, "会员不存在");

        MemberAuthInfoDTO memberAuth = new MemberAuthInfoDTO()
                .setMemberId(member.getId())
                .setUsername(member.getMobile())
                .setStatus(member.getStatus());
        return memberAuth;
    }

    /**
     * 新增会员
     *
     * @param memberDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addMember(MemberRegisterDTO memberDTO) {
        //判断手机验证码是否正确
        String code = (String) redisUtils.get(SecurityConstants.SMS_CODE_PREFIX_REGISTER + memberDTO.getMobile());
        if (StringUtils.isEmpty(memberDTO.getCaptcha()) || !memberDTO.getCaptcha().equals(code)){
            throw new RemindException(RemindCode.MESSAGE_CODE_ERROR_REMIND);
        }

        //判断手机号是否注册
        SysMember sysMember = this.getOne(new LambdaQueryWrapper<SysMember>()
                .eq(SysMember::getMobile, memberDTO.getMobile())
                .select(SysMember::getId)
        );
        if (sysMember!=null && sysMember.getId()!=null){
            throw new RemindException(RemindCode.PHONE_USER_EXIST_REMIND);
        }

        redisUtils.del(SecurityConstants.SMS_CODE_PREFIX_REGISTER + memberDTO.getMobile());

        //设置并保存账号信息
        sysMember = BeanUtils.copy(memberDTO, SysMember.class);
        sysMember.initMember();
        sysMember.setStatus(WechatConstant.MEMBER_NORMAL);
        sysMember.setId(idWorker.nextId());

        //加密密码
        if (StringUtils.isNotEmpty(sysMember.getPassword())) {
            sysMember.setPassword(PasswordUtil.encrypt(sysMember.getPassword(), SecurityConstants.PASSWORD_KEY, sysMember.getSalt()));
        }

        boolean result = this.save(sysMember);
        log.info("addMember | result:{},sysMember:{}",result, JSONObject.toJSONString(sysMember));
        return sysMember.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(String mobile, String oldpassword, String newpassword, String confirmpassword, String captcha) {
        //判断手机验证码是否正确
        String code = (String) redisUtils.get(SecurityConstants.SMS_CODE_PREFIX_FORGET + mobile);
        if (StringUtils.isEmpty(captcha) || !captcha.equals(code)){
            throw new RemindException(RemindCode.MESSAGE_CODE_ERROR_REMIND);
        }

        redisUtils.del(SecurityConstants.SMS_CODE_PREFIX_FORGET + mobile);

        SysMember sysMember = this.getOne(new LambdaQueryWrapper<SysMember>()
                .eq(SysMember::getMobile, mobile)
        );

        if (sysMember != null) {
            String passwordEncode = PasswordUtil.encrypt(oldpassword, SecurityConstants.PASSWORD_KEY, sysMember.getSalt());
            if (!sysMember.getPassword().equals(passwordEncode)) {
                throw new RemindException(RemindCode.USER_PASSWORD_ERROR_REMIND);
            }
            if (StringUtils.isEmpty(newpassword)) {
                throw new RemindException(RemindCode.USER_PASSWORD_NOT_NULL_REMIND);
            }
            if (!newpassword.equals(confirmpassword)) {
                throw new RemindException(RemindCode.USER_PASSWORD_SAME_OLD_REMIND);
            }
            String password = PasswordUtil.encrypt(newpassword, SecurityConstants.PASSWORD_KEY, sysMember.getSalt());
            this.update(new LambdaUpdateWrapper<SysMember>().eq(SysMember::getId, sysMember.getId()).set(SysMember::getPassword, password));
            log.info("resetPassword | username:{},newpassword:{}", mobile, password);
            return true;
        }
        return false;
    }

    /**
     * 获取登录会员信息
     *
     * @return
     */
    @Override
    public MemberVO getCurrentMemberInfo() {
        Long memberId = MemberUtils.getMemberId();
        SysMember sysMember = this.getOne(new LambdaQueryWrapper<SysMember>()
                .eq(SysMember::getId, memberId)
                .select(SysMember::getId,
                        SysMember::getNickName,
                        SysMember::getRealName,
                        SysMember::getAvatarUrl,
                        SysMember::getMobile,
                        SysMember::getEmail,
                        SysMember::getCompany,
                        SysMember::getStatus,
                        SysMember::getSex,
                        SysMember::getGmtCreate
                )
        );
        MemberVO memberVO = new MemberVO();
        BeanUtil.copyProperties(sysMember, memberVO);
        return memberVO;
    }

    /**
     * 获取登录会员信息
     *
     * @return
     */
    @Override
    public MemberVO getMemberInfoByMobile(String mobile) {
        SysMember sysMember = this.getOne(new LambdaQueryWrapper<SysMember>()
                .eq(SysMember::getMobile, mobile)
                .select(SysMember::getId,
                        SysMember::getNickName,
                        SysMember::getRealName,
                        SysMember::getAvatarUrl,
                        SysMember::getMobile,
                        SysMember::getBirthday,
                        SysMember::getEmail,
                        SysMember::getCompany,
                        SysMember::getStatus,
                        SysMember::getSex,
                        SysMember::getSourceType,
                        SysMember::getGmtCreate
                )
        );
        MemberVO memberVO = new MemberVO();
        BeanUtil.copyProperties(sysMember, memberVO);
        return memberVO;
    }

    @Override
    public void checkUserIsEffective(MemberVO memberVO) {
        //情况1：根据用户信息查询，该用户不存在
        if (memberVO == null) {
            throw new RemindException(RemindCode.USER_NO_ACCOUNT);
        }
        //情况2：根据用户信息查询，该用户已冻结
        if (GlobalConstants.USER_FREEZE.equals(memberVO.getStatus())) {
            throw new RemindException(RemindCode.USER_ACCOUNT_FREEZE);
        }
    }
}
